/**
 * 对业务数据的增删改进行落地
 */
package indi.zjh.dp.db;

import indi.zjh.dp.error.DatabaseUnwritableException;
import indi.zjh.dp.error.ParameterNotMatchException;
import indi.zjh.dp.orm.Business;
import indi.zjh.dp.util.SerializeUtil;

import java.sql.SQLException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import com.mysql.jdbc.MysqlDataTruncation;
import com.mysql.jdbc.exceptions.MySQLTimeoutException;
import com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException;

public class DataSource {
	
	public static final int CREATE = 0;
	public static final int UPDATE = 1;
	public static final int DELETE = 2;
	
	private static String tableName = "dsrc"; // 表名
	private static HashSet<String> ignoreClassNameSet = new HashSet<String>(); // 忽略写入数据库的类名
	private static String tranIdTableName = "trans"; // 用来记录事务全局Id的表名, 用来做数据库主从恢复数据
	
	
	public static void init(Session sess) throws SQLException, ParameterNotMatchException
	{
		sess.loadTables();
		if(!sess.isTableExist(tableName))
		{
			Table t = new Table(tableName);
			TField tf = new TField();

			tf.type = TField.TYPE_BIGINT;
			tf.isPrimary = true;
			tf.name = "_id";
			tf.length = 12;
			tf.comment = "自增Id";
			t.addField(tf);
			
			tf = new TField();
			tf.type = TField.TYPE_BIGINT;
			tf.name = "_oid";
			tf.length = 12;
			tf.comment = "业务对象Id";
			tf.defaultValue = "0";
			t.addField(tf);
			
			tf = new TField();
			tf.type = TField.TYPE_BLOB;
			tf.comment = "对象序列化";
			tf.name = "_obj";
			t.addField(tf);
			
			tf = new TField();
			tf.type = TField.TYPE_TEXT;
			tf.comment = "对象值";
			tf.name = "_val";
			t.addField(tf);
			
			tf = new TField();
			tf.type = TField.TYPE_STRING;
			tf.length = 128;
			tf.name = "_objclass";
			tf.comment = "对象类名";
			tf.defaultValue = "nil";
			t.addField(tf);
			
			tf = new TField();
			tf.type = TField.TYPE_SMALLINT;
			tf.name = "_t";
			tf.defaultValue = "0";
			tf.comment = "记录类型, 0:新增, 1:修改, 2:删除";
			t.addField(tf);
			
			tf = new TField();
			tf.type = TField.TYPE_DATETIME;
			tf.name = "_time";
			tf.comment = "记录入库时间";
			t.addField(tf);
	
			sess.alter(t.getCreateSql());
		}
		
		if(!sess.isTableExist(tranIdTableName))
		{
			Table t = new Table(tranIdTableName);
			TField tf = new TField();

			tf.type = TField.TYPE_BIGINT;
			tf.isPrimary = true;
			tf.name = "_tranid";
			tf.length = 12;
			tf.comment = "全局事务自增Id";
			t.addField(tf);
			
			tf = new TField();
			tf.type = TField.TYPE_INT;
			tf.name = "_serverid";
			tf.length = 4;
			tf.comment = "Mysql服务器Id";
			tf.defaultValue = "0";
			t.addField(tf);
			
			//System.out.println(t.getCreateSql());
			sess.alter(t.getCreateSql());
		}
	}
	
	public static void ignore(Class<?> cls)
	{
		ignoreClassNameSet.add(cls.getName());
	}
	
	public static String getTableName()
	{
		return tableName;
	}
	
	public static void commitTranscation(Session sess) throws MySQLSyntaxErrorException, MySQLTimeoutException, ParameterNotMatchException, DatabaseUnwritableException, SQLException
	{
		try
		{
			// 记录全局事务Id
			String sql = "INSERT INTO `"+tranIdTableName+"`(`_tranid`, `_serverid`) VALUES(DEFAULT, @@server_id)";
			if(Configuration.isMysql())
			{
				int ret = sess.execute(sql);
			}
			//System.out.println(sql+", ret="+ret);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	public static void add(Session sess, Business obj, int type) throws MysqlDataTruncation, MySQLSyntaxErrorException, MySQLTimeoutException, ParameterNotMatchException, DatabaseUnwritableException, SQLException
	{
		if(!Configuration.isMysql())
			return;
		if(ignoreClassNameSet.contains(obj.getClass().getName()))
			return;
		String sql = "INSERT INTO `"+tableName+"` VALUES(DEFAULT, ?, ?, ?, ?, DEFAULT, ?)";
		Object[] params = new Object[]{obj, obj.getClass().getName(), obj.getId(), type, obj.toString()};
		sess.execute(sql, params);
	}
	
	public static Business get(Session sess, long id) throws Exception
	{
		String sql = "SELECT `_obj`, `_objclass` FROM `"+tableName+"` WHERE `_id` = "+id;
		List<Map<String, Object>> res = sess.query(sql);
		if(res.size() == 0)
			return null;
		return (Business)res.get(0).get("_obj");
	}
	
	public static Business getLast(Session sess, long offset) throws Exception
	{
		String sql = "SELECT `_obj`, `_objclass` FROM `"+tableName+"` ORDER BY `_id` DESC LIMIT "+offset+", 1";
		List<Map<String, Object>> res = sess.query(sql);
		if(res.size() == 0)
			return null;
		return (Business)res.get(0).get("_obj");
	}
	
	public static Business getLast(Session sess) throws Exception
	{
		return getLast(sess, 0);
	}
	
	public static void print(Session sess, int len) throws Exception
	{
		String sql = "SELECT `_obj`, `_objclass`, `_t`, `_time` FROM `"+tableName+"` ORDER BY `_id` DESC LIMIT 0, "+len;
		List<Map<String, Object>> res = sess.query(sql);
		if(res.size() == 0)
			return;
		for(int i = 0; i < res.size(); ++i)
		{
			int type = (int)res.get(i).get("_t");
			String typestr = null;
			if(type == CREATE)
			{
				typestr = "创建";
			}
			else if(type == UPDATE)
			{
				typestr = "更新";
			}
			else {
				typestr = "删除";
			}
			Business obj = (Business)res.get(i).get("_obj");
			System.out.println(res.get(i).get("_time")+" "+typestr+" "+obj.toString());
		}
	}
}
